package concordia.comp6231.groupmembership;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.jgroups.Address;
import org.jgroups.JChannel;
import org.jgroups.ReceiverAdapter;
import org.jgroups.View;

import concordia.comp6231.common.ApplicationConfig;
import concordia.comp6231.leaderelection.LeaderElectionManager;
import concordia.comp6231.rfmulticast.RFIFOMulticast;
import concordia.comp6231.server.ReplicaMember;

public class GroupMembershipManager extends ReceiverAdapter {
	
    private JChannel channel;
    private static GroupMembershipManager instance;
    
    public static GroupMembershipManager currentInstance() {
    	if (instance == null) {
    		instance = new GroupMembershipManager();
    	}
    	return instance;
    }

	private GroupMembershipManager() {
	}
	
	public void startService() {
        try {
			channel=new JChannel();
			String groupName = ApplicationConfig.get(ApplicationConfig.REPLICA_GROUP_NAME);
			channel.setReceiver(this);
			channel.connect(groupName);
			channel.getState(null, 3000);
			System.out.println("Replica " + RFIFOMulticast.getMyHostName() + ", joined group: " + groupName);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
    public void viewAccepted(View newView) {
        System.out.println("Group members: " + newView);
        LeaderElectionManager.currentInstance().electNewLeader();
    }

    public List<String> getMembers() {
		List<String> members = new ArrayList<String>();
		List<Address> membersAddress = channel.getView().getMembers();
		for (Address address : membersAddress) {
			members.add(address.toString().split("-")[0]);
		}
		return Collections.unmodifiableList(members);
	}

	public List<String> getOtherMembers() {
		List<String> members = new ArrayList<String>();
		List<Address> membersAddress = channel.getView().getMembers();
		String me = RFIFOMulticast.getMyHostName();
		for (Address address : membersAddress) {
			String addressStr = address.toString().split("-")[0]; 
			if (!me.equals(addressStr)) {
				members.add(addressStr);
			}
		}
		return Collections.unmodifiableList(members);
	}
	
	public void disconnect() {
        try {
            channel.close();
        }
        catch(Exception ex) {
            System.err.println(ex);
        }
	}

}
